﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Target : MonoBehaviour {

    public static event System.Action OnDestroyedByArrow;

    public float maxMovementDistance = 4f;
    public float targetMoveSpeed = 2f;
    [Range(0,2)]
    public float easeCount = 1f;
    public float waitingTime = .5f;

    private float dir = 1;
    private Vector3 startPos;
    private Vector3[] targetMovementPos;
    private float easePercent;
    private float averagePercent;
    private float percentBetweenPositions;
    private float countTime;
    private bool isStop = false;
    private bool isMove = false;
    private Rigidbody rig;
    private float bounceHeight = 25f;
    private float minBounceParam = .3f;
    private GameObject targetHolder;

    private void Awake()
    {
        rig = gameObject.GetComponent<Rigidbody>();
        targetHolder = GameObject.Find("TargetHolder");
    }

    private void Start()
    {
        startPos = this.transform.position;
        targetMovementPos = new Vector3[2];
        targetMovementPos[0] = startPos + Vector3.up * maxMovementDistance / 2;
        targetMovementPos[1] = startPos - Vector3.up * maxMovementDistance / 2;
        waitingTime = Random.Range(waitingTime, waitingTime * 3);

        StartCoroutine(BounceBack());
    }

    private void Update()
    {
        if (isMove)
        {
            TargetMove();
        }
    }

    private void OnTriggerEnter(Collider other)
    {
        if(other.tag == "Ball")
        {
            //Debug.Log("Hit the target!");
            GameObject.Destroy(this.gameObject);
        }
    }

    float Ease(float x)
    {
        //Base on the equation of x^a / (x^a -(1-x)^a) tune the value of x from 0 to 1 where get ease curve.
        float a = easeCount + 1;
        return Mathf.Pow(x, a) / (Mathf.Pow(x, a) + Mathf.Pow(1 - x, a));
    }

    void TargetMove()
    {
        if (isStop) {
            if(Time.time - countTime > waitingTime)
            {
                isStop = false;
            }else
            {
                return;
            }
            
        }

        averagePercent = targetMoveSpeed * Time.deltaTime * dir;
        percentBetweenPositions += averagePercent;
        percentBetweenPositions = Mathf.Clamp01(percentBetweenPositions);
        easePercent = Ease(percentBetweenPositions);
        if (easePercent >= 1 || easePercent <= 0)
        {
            dir *= -1;
            isStop = true;
            countTime = Time.time;
        }
        transform.position = Vector3.Lerp(targetMovementPos[1], targetMovementPos[0], easePercent);
    }

    public void SetTargetMovement(bool move)
    {
        if (move)
        {
            isMove = true;
        }else{
            isMove = false;
        }
    }

    private void OnDestroy()
    {
        if(OnDestroyedByArrow != null)
        {
            OnDestroyedByArrow();
        }
    }

    public float CalculateUpwardSpeed(float height)
    {
        float speed = Mathf.Sqrt(2 * Mathf.Abs(BallControl.gravity) * height);
        return speed;
    }

    public void SetTargetVelocity()
    {
        float randomHeight = Random.Range(bounceHeight * minBounceParam, bounceHeight);
        rig.velocity = CalculateUpwardSpeed(randomHeight) * Vector3.up;
    }
    
    IEnumerator BounceBack()
    {
        while(this.transform.position.y > targetHolder.transform.position.y)
        {
            yield return null;
        }

        rig.velocity = Vector3.zero;
        rig.useGravity = false;
        yield return new WaitForSeconds(Random.value * 2);
        rig.useGravity = true;
        this.transform.position = new Vector3(this.transform.position.x, targetHolder.transform.position.y + 0.2f, this.transform.position.z);
        SetTargetVelocity();
        StartCoroutine(BounceBack());
    }
}
